﻿using System;
using System.Security.Cryptography.X509Certificates;
using eWallet.Security.Cryptography;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Security.Cryptography;
using System.Text;
using eWallet.Serialization;
using System.Collections.Generic;

namespace eWallet.Tests
{
	/// <summary>
	/// Summary description for CryptoTests
	/// </summary>
	[TestClass]
	public class CryptoTests
	{
		
		/// <summary>
		///Gets or sets the test context which provides
		///information about and functionality for the current test run.
		///</summary>
		public TestContext TestContext { get; set; }



		#region Test: public void DecryptData01()

		[global::Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute()]
		[global::Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute(" ")]
		public void DecryptData01()
		{
			PasswordCryptoModule module = new PasswordCryptoModule("12345");
			byte[] cipher = module.Encrypt<string>("Very much secret text.", CryptoModule.StringInputConverter);
			string data = module.Decrypt<string>(cipher, CryptoModule.StringOutputConverter);
			Assert.AreEqual<string>("Very much secret text.", data);
		}

		#endregion

		#region Test: public void DecryptData02()

		[global::Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute()]
		[global::Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute(" ")]
		public void DecryptData02()
		{
			string data = "lkajs dlfkajsdfl kasld flaksdj flaksjd fl kaj s dlfk alskdfj alkdsjf laksdj flakj dflkaj dslfk jalksdf jlakj sdlfk jasldkfj alksdjf laksjdf laksjdj flakjsd f l kajsldkfj alsdkjf laksdjf laksjdf laksjd flkajd lfkaj ldkfj alkdsjf laksjd flaksdjf lkjlkj#";
			string pwd = "MyPassword";
			PasswordCryptoModule module = new PasswordCryptoModule(pwd);
			byte[] cipher = module.Encrypt<string>(data, CryptoModule.StringInputConverter);
			string data2 = module.Decrypt<string>(cipher, CryptoModule.StringOutputConverter);
			Assert.AreEqual<string>(data, data2);
		}

		#endregion

		#region Test: public void DecryptData03()

		[global::Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute()]
		[global::Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute("Decrypts cipher data that has been encrypted earlier. This ensures that encrypted data can be decrypted at a later point, possibly spanning several versions of this library.")]
		public void DecryptData03()
		{
			string data = "Hello World!";
			string pwd = "alksdjf lakdfj alskdjf laksdfj laskdjf lakdfj lakdsjf lakjd flkajoidsfoqiewuo iqoweiur oique o tiquwe otroqwiu oiu45oi23u4oi5uo3 i4u5 oi3u4 5oiu3o4i5jo23i2 45oiu 3o4i5u o3iu4j5o i3u4 o5iujo3w4i5";
			byte[] cipher = new byte[] { 31, 255, 215, 253, 90, 205, 120, 154, 203, 225, 209, 190, 211, 228, 254, 220 };
			string decrypt = new PasswordCryptoModule(pwd).Decrypt<string>(cipher, CryptoModule.StringOutputConverter);
			Assert.AreEqual<string>(data, decrypt);
		}

		#endregion

		#region Test: public void DecryptData04()

		[global::Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute()]
		[global::Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute("Encrypts data with a certificate and makes sure that it can be decrypted with the same key.")]
		public void DecryptData04()
		{
			string data = "lkj2l34 5lk324j5 lk23j4 5lkj23l4 5l2k45 lkj2 34lk5j 2l3k54j l2kjlkjlk4j5l6kj5lk6j7lkjsdgl ksdl ksadjfl l3k45j6l";
			X509Certificate2 cert = new X509Certificate2(Properties.Resources.eWalletTestCertificate1);
			var module = new CertificationCryptoModule(cert);
			byte[] cipher = module.Encrypt<string>(data, CryptoModule.StringInputConverter);
			string newData = module.Decrypt<string>(cipher, CryptoModule.StringOutputConverter);
			Assert.AreEqual<string>(data, newData);
		}

		#endregion

		#region Test: public void DecryptData05()

		[global::Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute()]
		[global::Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute(" ")]
		[ExpectedException(typeof(CryptographicException))]
		public void DecryptData05()
		{
			string data1 = "This is encrypted data!";
			string pwd1 = "laksdflka jdlkja lsdkf aldf lakdf lakdf lakdf lkajdf lkadflkajsdlfk aldkf aljf";
			string pwd2 = "laksdflka jdlkja lsdkf aldf lakdf lakde lakdf lkajdf lkadflkajsdlfk aldkf aljf";

			byte[] cipher = new PasswordCryptoModule(pwd1).Encrypt<string>(data1, CryptoModule.StringInputConverter);
			string data2 = new PasswordCryptoModule(pwd2).Decrypt<string>(cipher, CryptoModule.StringOutputConverter);
		}

		#endregion

		#region Test: public void DecryptData06()

		[global::Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute()]
		[global::Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute(" ")]
		[ExpectedException(typeof(CryptographicException))]
		public void DecryptData06()
		{
			string data1 = "ljalsdf laf laf öasdf öaf alskdf laksdjf lkasf laksjf las alsdfh asdflj l";
			X509Certificate2 cert1 = new X509Certificate2(Properties.Resources.eWalletTestCertificate1);
			X509Certificate2 cert2 = new X509Certificate2(Properties.Resources.eWalletTestCertificate2);

			byte[] cipher = new CertificationCryptoModule(cert1).Encrypt<string>(data1, CryptoModule.StringInputConverter);
			string data2 = new CertificationCryptoModule(cert2).Decrypt<string>(cipher, CryptoModule.StringOutputConverter);
		}

		#endregion
		


		#region Test: public void DecryptSymmetricAlgorithm01()

		[global::Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute()]
		[global::Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute(" ")]
		public void DecryptSymmetricAlgorithm01()
		{
			string pwd = "ljlkjlkj18$";
			PasswordCryptoModule module = new PasswordCryptoModule(pwd);

			var algo = SymmetricAlgorithm.Create("Rijndael");
			var cipher = module.Encrypt<SymmetricAlgorithm>(algo, CryptoModule.SymmetricAlgorithmInputConverter);
			var algo2 = module.Decrypt<SymmetricAlgorithm>(cipher, CryptoModule.SymmetricAlgorithmOutputConverter);

			Assert.IsNotNull(algo2);
			Assert.AreEqual<Type>(algo.GetType(), algo2.GetType());
			CollectionAssert.AreEqual(algo.IV, algo2.IV);
			CollectionAssert.AreEqual(algo.Key, algo2.Key);
		}

		#endregion

		#region Test: public void DecryptSymmetricAlgorithm02()

		[global::Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute()]
		[global::Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute(" ")]
		public void DecryptSymmetricAlgorithm02()
		{
			X509Certificate2 cert = new X509Certificate2(Properties.Resources.eWalletTestCertificate2);
			var module = new CertificationCryptoModule(cert);

			var algo = SymmetricAlgorithm.Create("Rijndael");
			var cipher = module.Encrypt<SymmetricAlgorithm>(algo, CryptoModule.SymmetricAlgorithmInputConverter);
			var algo2 = module.Decrypt<SymmetricAlgorithm>(cipher, CryptoModule.SymmetricAlgorithmOutputConverter);

			Assert.IsNotNull(algo2);
			Assert.AreEqual<Type>(algo.GetType(), algo2.GetType());
			CollectionAssert.AreEqual(algo.IV, algo2.IV);
			CollectionAssert.AreEqual(algo.Key, algo2.Key);
		}

		#endregion
		
		

		#region Test: public void EncryptData01()

		[global::Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute()]
		[global::Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute(" ")]
		public void EncryptData01()
		{
			byte[] cipher = new PasswordCryptoModule("12345").Encrypt<string>("Very much secret text.", CryptoModule.StringInputConverter);
			Assert.IsNotNull(cipher);
		}

		#endregion

		#region Test: public void EncryptData02()

		[global::Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute()]
		[global::Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute("Encrypts the same data with passwords that only differ in case and asserts that the resulting cipher data is not the same.")]
		public void EncryptData02()
		{
			string data = "If you can read this text, you have successfully decrypted the cipher message. Congrats!";
			string pwd1 = "Password";
			string pwd2 = "PassworD";

			byte[] cipher1 = new PasswordCryptoModule(pwd1).Encrypt<string>(data, CryptoModule.StringInputConverter);
			byte[] cipher2 = new PasswordCryptoModule(pwd2).Encrypt<string>(data, CryptoModule.StringInputConverter);

			CollectionAssert.AreNotEqual(cipher1, cipher2);

			// Also ensure that even though the passwords are equal in the beginning,
			// the first byte of the cipher must not be equal.
			Assert.AreNotEqual<byte>(cipher1[0], cipher2[0]);
		}

		#endregion

		#region Test: public void EncryptData03()

		[global::Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute()]
		[global::Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute("Encrypts the same data twice with the same password, and asserts that the cipher data is the same.")]
		public void EncryptData03()
		{
			string data = "lkja lkj lwwkjl43k5j l3k4j5 l3k4j56l k3j4 5lk3j4l5kj3l4k5 jl3k4j5 lk3j4l 5kjlkj";
			string pwd = "MyPassword";
			var module = new PasswordCryptoModule(pwd);

			byte[] cipher1 = module.Encrypt<string>(data, CryptoModule.StringInputConverter);
			byte[] cipher2 = module.Encrypt<string>(data, CryptoModule.StringInputConverter);

			CollectionAssert.AreEqual(cipher1, cipher2);
		}

		#endregion

		#region Test: public void EncryptData04()

		[global::Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute()]
		[global::Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute("Encrypts data using a certificate and ensures that the encrypted data is not null.")]
		public void EncryptData04()
		{
			string data = "lkjlkj l23k4j5 lkj3 4l5kj l3k4j5 lkj3 4l5kjl3k4j5lkj34 l5kj l3k5j6lk4jl7kj";
			var cert = new X509Certificate2(Properties.Resources.eWalletTestCertificate1);
			byte[] cipher = new CertificationCryptoModule(cert).Encrypt<string>(data, CryptoModule.StringInputConverter);
			Assert.IsNotNull(cipher);
		}

		#endregion



		#region Test: public void EncryptSymmetricAlgorithm01()

		[global::Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute()]
		[global::Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute(" ")]
		public void EncryptSymmetricAlgorithm01()
		{
			var algo = SymmetricAlgorithm.Create("Rijndael");
			var cipher = new PasswordCryptoModule("lkjlkjlkj").Encrypt<SymmetricAlgorithm>(algo, CryptoModule.SymmetricAlgorithmInputConverter);
			Assert.IsNotNull(cipher);
		}

		#endregion

		#region Test: public void EncryptSymmetricAlgorithm02()

		[global::Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute()]
		[global::Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute(" ")]
		public void EncryptSymmetricAlgorithm02()
		{
			var algo = SymmetricAlgorithm.Create("Rijndael");
			var cert = new X509Certificate2(Properties.Resources.eWalletTestCertificate1);
			var cipher = new CertificationCryptoModule(cert).Encrypt<SymmetricAlgorithm>(algo, CryptoModule.SymmetricAlgorithmInputConverter);
			Assert.IsNotNull(cipher);
		}

		#endregion



		#region Test: public void GetCryptoDescription01()

		[global::Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute()]
		[global::Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute(" ")]
		public void GetCryptoDescription01()
		{
			PasswordCryptoModule mod = new PasswordCryptoModule("1234");
			Assert.IsNotNull(mod.GetDescription());
		}

		#endregion

		#region Test: public void GetCryptoDescription03()

		[global::Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute()]
		[global::Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute(" ")]
		public void GetCryptoDescription03()
		{
			X509Certificate2 cert = new X509Certificate2(Properties.Resources.eWalletTestCertificate1);
			CertificationCryptoModule mod = new CertificationCryptoModule(cert);
			Assert.IsNotNull(mod.GetDescription());
		}

		#endregion

		#region Test: public void GetCryptoDescription05()

		[global::Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute()]
		[global::Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute(" ")]
		public void GetCryptoDescription05()
		{
			SymmetricAlgorithm alg = SymmetricAlgorithm.Create("Rijndael");
			SymmetricKeyCryptoModule mod = new SymmetricKeyCryptoModule(alg);
			Assert.IsNotNull(mod.GetDescription());
		}

		#endregion
		
	}
}
